#include <stdio.h>
#include <kernel/syscall.h>
#include <kernel/xtTask.h>

#define	Mode_MASK       0x1F
#define	Mode_USR        0x10
#define	Mode_FIQ     		0x11
#define	Mode_IRQ      	0x12
#define	Mode_SVC       	0x13
#define	Mode_ABT     		0x17
#define	Mode_UND       	0x1B
#define	Mode_SYS       	0x1F
#define	I_Bit           0x80
#define	F_Bit           0x40

extern xtScheduler * __scheduler;

void uartPrintf (char * args, ...) {}
static void showProcessState (char * message, xt_u32_t cpsr, xt_stack_t * stack)
{
	kprintf(message);
	
	kprintf("Process state:\n");
	kprintf("R0:%#x, R1:%#x, R2:%#x, R3:%#x, R4:%#x, R5:%#x, R6:%#x, R7:%#x, R8:%#x,"
					"R9:%#x, R10:%#x, R11:%#x, R12:%#x, PC:%#x\n",
					stack[0], stack[1], stack[2], stack[3], stack[4], stack[5], stack[6], stack[7],
					stack[8], stack[9], stack[10], stack[11], stack[12], stack[13]);
	kprintf("CPSR:0x%x ", cpsr);
	switch (cpsr & Mode_MASK) {
		case Mode_USR: kprintf("Mode:User "); break;
		case Mode_FIQ: kprintf("Mode:FIQ "); break;
		case Mode_IRQ: kprintf("Mode:IRQ "); break;
		case Mode_SVC: kprintf("Mode:SVC "); break;
		case Mode_ABT: kprintf("Mode:ABT "); break;
		case Mode_UND: kprintf("Mode:UND "); break;
		case Mode_SYS: kprintf("Mode:SYS "); break;
	}
	kprintf(" IRQ:%s", (cpsr & I_Bit) ? "Disable" : "Enable");
	kprintf(" FIQ:%s", (cpsr & F_Bit) ? "Disable" : "Enable");
	
	if (__scheduler) {
		xtTask * task = __scheduler->currentTask();
		if (task) {
			kprintf("\nTask information:\n");
			kprintf("\nName:%s, priority:%d \n", task->name(), task->priority());
		}
	}
}

extern "C" void do_SWI_Handler (int syscallNum, xt_stack_t * stack)
{
	if (syscallNum == XT_SYSCALL_NUM) {
	}
}

extern "C" void do_Undef_Handler (xt_u32_t cpsr, xt_stack_t * stack)
{
	showProcessState("Undefined instruction Exception!\n", cpsr, stack);
	while (1);
}

extern "C" void do_PAbt_Handler (xt_u32_t cpsr, xt_stack_t * stack)
{
	showProcessState("Prefetch abort Exception!\n", cpsr, stack);
	while (1);
}

extern "C" void do_DAbt_Handler (xt_u32_t cpsr, xt_stack_t * stack)
{
	showProcessState("Data abort Exception!\n", cpsr, stack);
	while (1);
}

extern "C" void do_IRQ_Handler (xt_u32_t cpsr, xt_stack_t * stack)
{
	while (1);
}

extern "C" void do_FIQ_Handler (xt_u32_t cpsr, xt_stack_t * stack)
{
	while (1);
}
